home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
init.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
10KB
|
382 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: init.c,v 1.62 2001/03/03 01:00:05 drscholl Exp $ */
/* Modified 30/05/01 : Added defines for USE_GID and USE_UID, since we are not
for Amiga port : using the CONFIGURE script
Added include "confdefs.h" since we are not using the
CONFIGURE script
Added include "extrasocket.h" with inlines for a few
bsdsocket.library functions not emulated by ixemul
*/
#define USE_GID "nobody"
#define USE_UID "nobody"
#include "confdefs.h"
#ifndef WIN32
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <limits.h>
#if HAVE_MLOCKALL
#include <sys/mman.h>
#endif /* HAVE_MLOCKALL */
#endif /* !WIN32 */
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#ifndef WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef __EMX__
#include <stdlib.h>
#define _POSIX_PATH_MAX _MAX_PATH
#endif /* __EMX__ */
#include "opennap.h"
#include "hashlist.h"
#include "debug.h"
#include "extrasocket.h"
static void
lookup_hostname (void)
{
struct hostent *he;
/* get our canonical host name */
gethostname (Buf, sizeof (Buf));
he = gethostbyname (Buf);
if (he)
Server_Name = STRDUP (he->h_name);
else
{
log ("lookup_hostname: unable to find fqdn for %s", Buf);
Server_Name = STRDUP (Buf);
}
}
#if !defined( WIN32) || defined(__CYGWIN__)
static void
sighandler (int sig)
{
log ("sighandler: caught signal %d", sig);
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
SigCaught = 1;
break;
case SIGUSR1:
CLEANUP ();
break;
}
}
#if defined(PARANOID) && defined(DEBUG)
static void
wipe_user_pass (USER * user, void *unused)
{
(void) unused;
memset (user->pass, 0, strlen (user->pass));
}
static void
wipe_server_pass (server_auth_t * auth)
{
memset (auth->their_pass, 0, strlen (auth->their_pass));
memset (auth->my_pass, 0, strlen (auth->my_pass));
}
static void
handle_sigsegv (int sig)
{
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = SIG_DFL;
sigaction (SIGSEGV, &sa, 0); /* set back to default */
/* every C primer says not to do this, but it seems to work... =) */
fprintf (stderr, "handle_sigsegv: caught sigsegv, wiping passwords\n");
fflush (stderr);
(void) sig;
/* wipe the user/server passwords before dumping core */
hash_foreach (User_Db, (hash_callback_t) wipe_user_pass, 0);
list_foreach (Server_Auth, (list_callback_t) wipe_server_pass, 0);
kill (getpid (), SIGSEGV); /* raise the signal again so we get a core */
}
#endif /* PARANOID */
static int
drop_privs (void)
{
int n;
char *p;
struct passwd *pw;
struct group *gr;
n = strtol (USE_GID, &p, 10);
if (p)
{
/* probably a string */
gr = getgrnam (USE_GID);
if (!gr)
{
log ("drop_privs: unable to find gid for group %s", USE_GID);
return -1;
}
n = gr->gr_gid;
}
if (setgid (n))
{
logerr ("drop_privs", "setgid");
return -1;
}
n = strtol (USE_UID, &p, 10);
if (p)
{
/* probably a string */
pw = getpwnam (USE_UID);
if (!pw)
{
log ("drop_privs: unable to find uid for user %s", USE_UID);
return -1;
}
n = pw->pw_uid;
}
if (setuid (n))
{
logerr ("drop_privs", "setuid");
return -1;
}
return 0;
}
#endif
/* write the pid to a file so an external program can check to see if the
process is still running. */
static void
dump_pid (void)
{
FILE *f;
char path[_POSIX_PATH_MAX];
log ("dump_pid: pid is %d", getpid ());
snprintf (path, sizeof (path), "%s/pid", Config_Dir);
f = fopen (path, "w");
if (!f)
{
logerr ("dump_pid", path);
return;
}
fprintf (f, "%d\n", (int) getpid ());
fclose (f);
}
int
init_server (void)
{
#if !defined( WIN32) || defined(__CYGWIN__)
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = sighandler;
sigaction (SIGHUP, &sa, NULL);
sigaction (SIGTERM, &sa, NULL);
sigaction (SIGINT, &sa, NULL);
sigaction (SIGPIPE, &sa, NULL);
#if !defined( __EMX__) && !defined(__CYGWIN__)
sa.sa_flags = SA_RESTART;
#endif /* ! __EMX__ */
sigaction (SIGUSR1, &sa, NULL);
sigaction (SIGALRM, &sa, NULL);
#ifdef PARANOID
#ifndef DEBUG
sa.sa_handler = handle_sigsegv;
sigaction (SIGSEGV, &sa, NULL);
#endif /* DEBUG */
#endif /* PARANOID */
#endif /* !WIN32 */
global.stat_server_fd = -1;
log ("init_server: version %s starting", VERSION);
Server_Start = time (&global.current_time);
/* load default configuration values */
config_defaults ();
/* load the config file - note that if CHROOT is defined we are already
* chrooted when we get here. we are also running as uid 0 because
* some of the ulimit's might need to be altered before starting up.
* so read the config file now, set limits and then drop privs before
* loading any other files.
*/
if (config (1))
return -1;
#if !defined(WIN32) && !defined(__EMX__)
/* change umask to something more secure */
umask (077);
if (set_max_connections (Connection_Hard_Limit))
return -1;
if (Max_Data_Size != -1 && set_data_size (Max_Data_Size))
return -1;
if (Max_Rss_Size != -1 && set_rss_size (Max_Rss_Size))
return -1;
#if HAVE_MLOCKALL
/* prevent swapping by locking all memory into real memory */
if (option (ON_LOCK_MEMORY) && mlockall (MCL_CURRENT | MCL_FUTURE))
logerr ("init_server", "mlockall");
#endif /* HAVE_MLOCKALL */
if (getuid () == 0)
drop_privs ();
ASSERT (getuid () != 0);
ASSERT (getgid () != 0);
/* log message to show that we really have dropped privs. if CHROOT
* was defined, we should also be locked in the jail. we never need
* root privs again and only the config files need to be accessed.
*/
log ("init_server: running as user %d, group %d", getuid (), getgid ());
#endif /* !WIN32 */
#ifndef WIN32
/* if running in daemon mode, reopen stdout as a log file */
if (Server_Flags & ON_BACKGROUND)
{
char path[_POSIX_PATH_MAX];
int fd;
snprintf (path, sizeof (path), "%s/log", Config_Dir);
fd = open (path, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR);
if (fd > 0)
{
/* close stdout */
if (dup2 (fd, 1) == -1)
{
logerr ("init_server", "dup2");
return -1;
}
close (fd);
}
else
{
logerr ("init_server", path);
return -1;
}
}
#endif
dump_pid ();
/* if not defined in the config file, get the system name */
if (!Server_Name)
lookup_hostname ();
log ("init_server: my hostname is %s", Server_Name);
/* read the user database. we do this even for routing servers so that
* we keep track of who is allowed to log in. eventually this should
* probably just keep track of the few users that are allowed instead of
* keeping everyone...
*/
if (userdb_init ())
{
log ("init_server: userdb_init failed");
return -1;
}
/* initialize hash tables. the size of the hash table roughly cuts
the max number of matches required to find any given entry by the same
factor. so a 256 entry hash table with 1024 entries will take rougly
4 comparisons max to find any one entry. we use prime numbers here
because that gives the table a little better spread */
Users = hash_init (521, (hash_destroy) free_user);
Channels = hash_init (257, (hash_destroy) free_channel);
Hotlist = hash_init (521, 0);
Who_Was = hash_init (1027, (hash_destroy) free_whowas);
Clones = hash_init (1027, (hash_destroy) ip_info_free);
hash_set_hash_func (Clones, hash_u_int, hash_compare_u_int);
/* routing-only servers don't care about any of this crap... */
#ifndef ROUTING_ONLY
File_Table = hash_init (2053, 0);
#if RESUME
MD5 = hash_init (2053, 0);
#endif
load_bans ();
load_block ();
load_filter ();
load_channels ();
acl_init ();
#endif /* !ROUTING_ONLY */
Client_Versions = hash_init (257, (hash_destroy) hashlist_free);
init_random ();
motd_init ();
load_server_auth ();
/* figure out what my local ip address is so that when users connect via
* localhost they can still xfer files. do this here because
* server_name can get changed to server_alias below.
*/
Interface = inet_addr (Listen_Addr);
if (Interface != INADDR_ANY)
Server_Ip = Interface;
else
Server_Ip = lookup_ip (Server_Name);
#ifndef ROUTING_ONLY
/* set default values for napigator reporting if they were not
* explicitly set in the config file
*/
if (global.report_name == NULL)
global.report_name = STRDUP (Server_Name);
if (global.report_ip == NULL)
global.report_ip = STRDUP (my_ntoa (Server_Ip));
if (global.report_port == 0)
global.report_port = atoi (Server_Ports->data);
if (global.stat_server)
log ("init: napigator reporting set to %s -> %s:%d",
global.report_name, global.report_ip, global.report_port);
#endif
if (Server_Alias)
{
/* switch to using the alias if its defined. we delay until here
* because we need to find the local servers' ip when clients connect
* via localhost.
*/
if (Server_Name)
FREE (Server_Name);
Server_Name = STRDUP (Server_Alias);
log ("init_server: using %s as my name", Server_Name);
}
return 0;
}